home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / elv18src.zip / redraw.c < prev    next >
C/C++ Source or Header  |  1994-01-10  |  27KB  |  1,349 lines

  1. /* redraw.c */
  2.  
  3. /* Author:
  4.  *    Steve Kirkendall
  5.  *    14407 SW Teal Blvd. #C
  6.  *    Beaverton, OR 97005
  7.  *    kirkenda@cs.pdx.edu
  8.  */
  9.  
  10.  
  11. /* This file contains functions that draw text on the screen.  The major entry
  12.  * points are:
  13.  *    redrawrange()    - called from modify.c to give hints about what parts
  14.  *              of the screen need to be redrawn.
  15.  *    redraw()    - redraws the screen (or part of it) and positions
  16.  *              the cursor where it belongs.
  17.  *    idx2col()    - converts a markidx() value to a logical column number.
  18.  */
  19.  
  20. #include "config.h"
  21. #include "vi.h"
  22. #ifdef CRUNCH
  23. # define NEAR    LINES
  24. #else
  25. # define NEAR    (*o_nearscroll&0xff)
  26. #endif
  27.  
  28. /* This variable contains the line number that smartdrawtext() knows best */
  29. static long smartlno;
  30.  
  31. /* This function remembers where changes were made, so that the screen can be
  32.  * redrawn in a more efficient manner.
  33.  */
  34. static long    redrawafter;    /* line# of first line that must be redrawn */
  35. static long    preredraw;    /* line# of last line changed, before change */
  36. static long    postredraw;    /* line# of last line changed, after change */
  37. static int    mustredraw;    /* boolean: anything forcing a screen update? */
  38. void redrawrange(after, pre, post)
  39.     long    after;    /* lower bound of redrawafter */
  40.     long    pre;    /* upper bound of preredraw */
  41.     long    post;    /* upper bound of postredraw */
  42. {
  43.     if (after == redrawafter)
  44.     {
  45.         /* multiple insertions/deletions at the same place -- combine
  46.          * them
  47.          */
  48.         preredraw -= (post - pre);
  49.         if (postredraw < post)
  50.         {
  51.             preredraw += (post - postredraw);
  52.             postredraw = post;
  53.         }
  54.         if (redrawafter > preredraw)
  55.         {
  56.             redrawafter = preredraw;
  57.         }
  58.         if (redrawafter < 1L)
  59.         {
  60.             redrawafter = 0L;
  61.             preredraw = postredraw = INFINITY;
  62.         }
  63.     }
  64.     else if (postredraw > 0L)
  65.     {
  66.         /* multiple changes in different places -- redraw everything
  67.          * after "after".
  68.          */
  69.         postredraw = preredraw = INFINITY;
  70.         if (after < redrawafter)
  71.             redrawafter = after;
  72.     }
  73.     else
  74.     {
  75.         /* first change */
  76.         redrawafter = after;
  77.         preredraw = pre;
  78.         postredraw = post;
  79.     }
  80.     mustredraw = TRUE;
  81. }
  82.  
  83.  
  84. #ifndef NO_CHARATTR
  85. /* see if a given line uses character attribute strings */
  86. static int hasattr(lno, text)
  87.     long        lno;    /* the line# of the cursor */
  88.     REG char    *text;    /* the text of the line, from fetchline */
  89. {
  90.     static long    plno;    /* previous line number */
  91.     static long    chgs;    /* previous value of changes counter */
  92.     static int    panswer;/* previous answer */
  93.     char        *scan;
  94.  
  95.     /* if charattr is off, then the answer is "no, it doesn't" */
  96.     if (!*o_charattr)
  97.     {
  98.         chgs = 0; /* <- forces us to check if charattr is later set */
  99.         return FALSE;
  100.     }
  101.  
  102.     /* if we already know the answer, return it... */
  103.     if (lno == plno && chgs == changes)
  104.     {
  105.         return panswer;
  106.     }
  107.  
  108.     /* get the line & look for "\fX" */
  109.     if (!text[0] || !text[1] || !text[2])
  110.     {
  111.         panswer = FALSE;
  112.     }
  113.     else
  114.     {
  115.         for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
  116.         {
  117.         }
  118.         panswer = (scan[2] != '\0');
  119.     }
  120.  
  121.     /* save the results */
  122.     plno = lno;
  123.     chgs = changes;
  124.  
  125.     /* return the results */
  126.     return panswer;
  127. }
  128. #endif
  129.  
  130.  
  131. #ifndef NO_VISIBLE
  132. /* This function checks to make sure that the correct lines are shown in
  133.  * reverse-video.  This is used to handle the "v" and "V" commands.
  134.  */
  135. static long    vizlow, vizhigh;    /* the starting and ending lines */
  136. static int    vizleft, vizright;    /* starting & ending indicies */
  137. static int    vizchange;        /* boolean: must use stupid drawtext? */
  138. static void setviz(curs)
  139.     MARK        curs;
  140. {
  141.     long        newlow, newhigh;
  142.     long        extra = 0L;
  143.  
  144.     /* for now, assume the worst... */
  145.     vizchange = TRUE;
  146.  
  147.     /* set newlow & newhigh according to V_from and cursor */
  148.     if (!V_from)
  149.     {
  150.         /* no lines should have reverse-video */
  151.         if (vizlow)
  152.         {
  153.             redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
  154.             vizlow = vizhigh = 0L;
  155.         }
  156.         else
  157.         {
  158.             vizchange = FALSE;
  159.         }
  160.         return;
  161.     }
  162.  
  163.     /* figure out which lines *SHOULD* have hilites */
  164.     if (V_from < curs)
  165.     {
  166.         newlow = markline(V_from);
  167.         newhigh = markline(curs);
  168.         vizleft = markidx(V_from);
  169.         vizright = markidx(curs) + 1;
  170.     }
  171.     else
  172.     {
  173.         newlow = markline(curs);
  174.         newhigh = markline(V_from);
  175.         vizleft = markidx(curs);
  176.         vizright = markidx(V_from) + 1;
  177.     }
  178.  
  179.     /* adjust for line-mode hiliting */
  180.     if (V_linemd)
  181.     {
  182.         vizleft = 0;
  183.         vizright = BLKSIZE - 1;
  184.     }
  185.     else
  186.     {
  187.         extra = 1L;
  188.     }
  189.  
  190.     /* arrange for the necessary lines to be redrawn */
  191.     if (vizlow == 0L)
  192.     {
  193.         /* just starting to redraw */
  194.         redrawrange(newlow, newhigh, newhigh);
  195.     }
  196.     else
  197.     {
  198.         /* Were new lines added/removed at the front? */
  199.         if (newlow != vizlow)
  200.         {
  201.             if (newlow < vizlow)
  202.                 redrawrange(newlow, vizlow + extra, vizlow + extra);
  203.             else
  204.                 redrawrange(vizlow, newlow + extra, newlow + extra);
  205.         }
  206.  
  207.         /* Were new lines added/removed at the back? */
  208.         if (newhigh != vizhigh)
  209.         {
  210.             if (newhigh < vizhigh)
  211.                 redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
  212.             else
  213.                 redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
  214.         }
  215.     }
  216.  
  217.     /* remember which lines will contain hilighted text now */
  218.     vizlow = newlow;
  219.     vizhigh = newhigh;
  220. }
  221. #endif /* !NO_VISIBLE */
  222.  
  223.  
  224. /* This function converts a MARK to a column number.  It doesn't automatically
  225.  * adjust for leftcol; that must be done by the calling function
  226.  */
  227. int idx2col(curs, text, inputting)
  228.     MARK        curs;    /* the line# & index# of the cursor */
  229.     REG char    *text;    /* the text of the line, from fetchline */
  230.     int        inputting;    /* boolean: called from input() ? */
  231. {
  232.     static MARK    pcursor;/* previous cursor, for possible shortcut */
  233.     static MARK    pcol;    /* column number for pcol */
  234.     static long    chgs;    /* previous value of changes counter */
  235.     REG int        col;    /* used to count column numbers */
  236.     REG int        idx;    /* used to count down the index */
  237.     REG int        i;
  238.  
  239.     /* for now, assume we have to start counting at the left edge */
  240.     col = 0;
  241.     idx = markidx(curs);
  242.  
  243.     /* if the file hasn't changed & line number is the same & it has no
  244.      * embedded character attribute strings, can we do shortcuts?
  245.      */
  246.     if (chgs == changes
  247.      && !((curs ^ pcursor) & ~(BLKSIZE - 1))
  248. #ifndef NO_CHARATTR
  249.      && !hasattr(markline(curs), text)
  250. #endif
  251.     )
  252.     {
  253.         /* no movement? */
  254.         if (curs == pcursor)
  255.         {
  256.             /* return the column of the char; for tabs, return its last column */
  257.             if (text[idx] == '\t' && !inputting && !*o_list)
  258.             {
  259.                 return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
  260.             }
  261.             else
  262.             {
  263.                 return pcol;
  264.             }
  265.         }
  266.  
  267.         /* movement to right? */
  268.         if (curs > pcursor)
  269.         {
  270.             /* start counting from previous place */
  271.             col = pcol;
  272.             idx = markidx(curs) - markidx(pcursor);
  273.             text += markidx(pcursor);
  274.         }
  275.     }
  276.  
  277.     /* count over to the char after the idx position */
  278.     while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
  279.     {
  280.         if (i == '\t' && !*o_list)
  281.         {
  282.             col += *o_tabstop;
  283.             col -= col % *o_tabstop;
  284.         }
  285.         else if (i >= '\0' && i < ' ' || i == '\177')
  286.         {
  287.             col += 2;
  288.         }
  289. #ifndef NO_CHARATTR
  290.         else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
  291.         {
  292.             text += 2; /* plus one more at bottom of loop */
  293.             idx -= 2;
  294.         }            
  295. #endif
  296.         else
  297.         {
  298.             col++;
  299.         }
  300.         text++;
  301.         idx--;
  302.     }
  303.  
  304.     /* save stuff to speed next call */
  305.     pcursor = curs;
  306.     pcol = col;
  307.     chgs = changes;
  308.  
  309.     /* return the column of the char; for tabs, return its last column */
  310.     if (*text == '\t' && !inputting && !*o_list)
  311.     {
  312.         return col + *o_tabstop - (col % *o_tabstop) - 1;
  313.     }
  314.     else
  315.     {
  316.         return col;
  317.     }
  318. }
  319.  
  320.  
  321. /* This function is similar to idx2col except that it takes care of sideways
  322.  * scrolling - for the given line, at least.
  323.  */
  324. int mark2phys(m, text, inputting)
  325.     MARK    m;        /* a mark to convert */
  326.     char    *text;        /* the line that m refers to */
  327.     int    inputting;    /* boolean: caled from input() ? */
  328. {
  329.     int    i;
  330.  
  331.     i = idx2col(m, text, inputting);
  332.     while (i < leftcol)
  333.     {
  334.         leftcol -= *o_sidescroll;
  335.         mustredraw = TRUE;
  336.         redrawrange(1L, INFINITY, INFINITY);
  337.     }
  338.     while (i > rightcol)
  339.     {
  340.         leftcol += *o_sidescroll;
  341.         mustredraw = TRUE;
  342.         redrawrange(1L, INFINITY, INFINITY);
  343.     }
  344.     physrow = markline(m) - topline;
  345.     physcol = i - leftcol;
  346.     if (*o_number)
  347.         physcol += 8;
  348.  
  349.     return physcol;
  350. }
  351.  
  352. /* This function draws a single line of text on the screen.  The screen's
  353.  * cursor is assumed to be located at the leftmost column of the appropriate
  354.  * row.
  355.  */
  356. static void drawtext(text, lno, clr)
  357.     REG char    *text;    /* the text to draw */
  358.     long        lno;    /* the nu